package com.jht.bletool2java.util;

import android.content.Context;

public class ByteUtil {

    public static int byte1ToInt(byte b) {
        return b & 0xFF;
    }

    public static int byte1ToInt(byte[] b, int offset) {
        return b[offset] & 0xFF;
    }

    /**
     * convert byte to int, this method can handle the order (low bit before high bit)
     */
    public static int bytes2ToInt(byte[] src, int offset) {
        int value;
        value = (int) (((src[offset + 1] & 0xFF) << 8)
                | (src[offset] & 0xFF));
        return value;
    }

    public static int byte3ToInt(byte[] bytes, int off) {
        int b0 = bytes[off + 2] & 0xFF;
        int b1 = bytes[off + 1] & 0xFF;
        int b2 = bytes[off] & 0xFF;
        return (b0 << 16) | (b1 << 8) | b2;
    }

    public static int byte3ToIntR(byte[] bytes, int off) {
        int b2 = bytes[off + 2] & 0xFF;
        int b1 = bytes[off + 1] & 0xFF;
        int b0 = bytes[off] & 0xFF;
        return (b0 << 16) | (b1 << 8) | b2;
    }

    public static long byte5ToInt(byte[] bytes, int off) {
        long b0 = bytes[off + 4] & 0xFF;
        long b1 = bytes[off + 3] & 0xFF;
        long b2 = bytes[off + 2] & 0xFF;
        long b3 = bytes[off + 1] & 0xFF;
        long b4 = bytes[off] & 0xFF;
        return (b0 << 32) | (b1 << 24) | (b2 << 16) | (b3 << 8) | b4;
    }

    public static long byte5ToIntR(byte[] bytes, int off) {
        long b4 = bytes[off + 4] & 0xFF;
        long b3 = bytes[off + 3] & 0xFF;
        long b2 = bytes[off + 2] & 0xFF;
        long b1 = bytes[off + 1] & 0xFF;
        long b0 = bytes[off] & 0xFF;
        return (b0 << 32) | (b1 << 24) | (b2 << 16) | (b3 << 8) | b4;
    }

    public static int unsignedByteToInt(byte b) {
        return b & 0xFF;
    }

    public static int unsignedBytesToInt(byte lsb, byte msb) {
        return (unsignedByteToInt(lsb) + (unsignedByteToInt(msb) << 8));
    }

    public static int dip2px(Context context, float dpValue) {
        final float scale = context.getResources().getDisplayMetrics().density;
        return (int) (dpValue * scale + 0.5f);
    }

    public static int HL_byte2ToInt(byte[] src, int offset) {
        int value;
        value = (int) (((src[offset] & 0xFF) << 8)
                | (src[offset+1] & 0xFF));
        return value;
    }

    public static String getHexString(byte[] data){
        StringBuilder sb = new StringBuilder();
        for (byte datum : data) {
            String str = Integer.toHexString(ByteUtil.byte1ToInt(datum));
            if (str.length() == 1) {
                str = "0" + str;
            }
            sb.append(str).append(" - ");
        }
        return sb.toString();
    }

    public static String getHexStringNoSplit(byte[] data){
        StringBuilder sb = new StringBuilder();
        for (int i=0;i<data.length;i++){
            String str = Integer.toHexString(ByteUtil.byte1ToInt(data[i]));
            if (str.length() == 1){
                str = "0"+str;
            }
            sb.append(str);
        }
        return sb.toString();
    }

    public static String toHex(int data,int radix){
        int temp = data;
        StringBuilder sb = new StringBuilder();
        switch (radix){
            case 2:
                System.out.println("================2================");
                while(temp/2 >= 0){
                    int buffer = temp%2;
                    String c = "";
                    switch(buffer){
                        case 0:
                            c = "0";
                            break;
                        case 1:
                            c = "1";
                            break;
                    }
                    sb.insert(0,c);
                    if (temp/2 == 0){
                        break;
                    }
                    temp = temp/2;
                }
                break;
            case 16:
                System.out.println("================16================");
                while(temp/16 >= 0){
                    int buffer = temp%16;
                    String c = "";
                    switch(buffer){
                        case 0:
                            c = "0";
                            break;
                        case 1:
                            c = "1";
                            break;
                        case 2:
                            c = "2";
                            break;
                        case 3:
                            c = "3";
                            break;
                        case 4:
                            c = "4";
                            break;
                        case 5:
                            c = "5";
                            break;
                        case 6:
                            c = "6";
                            break;
                        case 7:
                            c = "7";
                            break;
                        case 8:
                            c = "8";
                            break;
                        case 9:
                            c = "9";
                            break;
                        case 10:
                            c = "a";
                            break;
                        case 11:
                            c = "b";
                            break;
                        case 12:
                            c = "c";
                            break;
                        case 13:
                            c = "d";
                            break;
                        case 14:
                            c = "e";
                            break;
                        case 15:
                            c = "f";
                            break;

                    }
                    sb.insert(0,c);
                    if (temp/16 == 0){
                        break;
                    }
                    temp = temp/16;
                }
                break;
            default:
                return "00";
        }
        return sb.toString();
    }

    /**
     * CRC-16/CCITT-FALSE x16+x12+x5+1 算法
     *
     * info
     * Name:CRC-16/CCITT-FAI
     * Width:16
     * Poly:0x1021
     * Init:0xFFFF
     * RefIn:False
     * RefOut:False
     * XorOut:0x0000
     *
     * @param bytes
     * @return
     */
    public static byte[] crc_16_CCITT_False(byte[] bytes) {
        int length = bytes.length;
        int crc = 0xffff; // initial value
        int polynomial = 0x1021; // poly value
        for (int index = 0; index < length; index++) {
            byte b = bytes[index];
            for (int i = 0; i < 8; i++) {
                boolean bit = ((b >> (7 - i) & 1) == 1);
                boolean c15 = ((crc >> 15 & 1) == 1);
                crc <<= 1;
                if (c15 ^ bit)
                    crc ^= polynomial;
            }
        }
        crc &= 0xffff;
        //输出String字样的16进制
        String strCrc = Integer.toHexString(crc).toUpperCase();
        byte[] result=new byte[2];
        result[0]=(byte)(crc&0xff);
        result[1]=(byte)((crc>>8)&0xff);
        return result;
    }
}

